package language.advanced;

public class OuterClass {
    private String str = "outer";
    public class inner {
//        static int a=10;  低版本jdk不支持内部类中的static修饰符
        public OuterClass getOuter(){
            System.out.println(str);  //内部类可以通过链接访问外部类的private属性
            return OuterClass.this;  //内部类可以通过.this引用外部类的对象
        }
    }

    public interface innerInterface{}
    private class privateInner implements innerInterface{}
    public privateInner getInner(){
        //更普遍的情况是，外部类有一个方法，该方法返回一个指向内部类的引用
        return new privateInner();
    }

    //在方法和if作用域内也可以创建内部类

    //创建一个实现了innerInterface接口的匿名内部类
    public innerInterface getAn(){
        return new innerInterface(){
            private int i = 10;
        };
    }

    //匿名内部类要么是扩展一个类，要么是实现一个接口，但是两者不可兼得 而且就算要实现接口，也只能实现一个
    public class Wrapper {
        public Wrapper(int x) {}
        public int getI(){
            return 0;
        };
    }
    public Wrapper getAnd(final int x){
        return new Wrapper(x){  //传递构造器参数
            private int i;
            {
                i = x;
                System.out.println("instance");
                //匿名类没有名字，所以不可能有命名的构造器。
                //借助实例初始化，我们可以在效果上为匿名内部类创建一个构造器
                //可以在初始化块中执行代码语句
            }
            public int getI(){return i;}
            public void a(){
//                x=1;  要用到一个在该匿名类之外定义的对象，需要等同final效果
            }
        };
    }

    //1. 不需要一个外部类对象来创建嵌套类对象；
    //2\无法从嵌套类对象内部访问非static的外部类对象
    ////衣会类可以包含其他静态元索
    public static String a = "bbb";
    public static class sta {
        private int  b =1;
        public void say(){
            System.out.println(a);
        }
    }

    public static void main(String[] args) {
        OuterClass dn = new OuterClass();
        inner dni = dn.new inner();  // 通过 .new创建内部类

        //完全阻止任何与类型相关的编码依赖，并且可以完全隐蔵实现细节，禁止向下转型
        innerInterface inner = dn.getInner();

        Wrapper and = dn.getAnd(10);
        System.out.println(and.getI());
        System.out.println(dni);
        System.out.println(dni.getOuter());
    }
}
